package test.com.linkgie.galaxyframework.httpproxy.core;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.linkgie.galaxyframework.httpproxy.HttpMethod;
import com.linkgie.galaxyframework.httpproxy.core.HttpProxy;
import com.linkgie.galaxyframework.utils.BinaryUtils;

/**
 * 用于收集请求信息的收集器；
 * <p>
 * 记录接收到的请求信息，用于验证是否与 {@link HttpProxy} 发送的内容一致，通过此方式验证 {@link HttpProxy}
 * 的运行正确性；
 * 
 * @author huanghaiquan
 *
 */
public class HttpRequestCollectorServlet extends HttpServlet {

	private static final long serialVersionUID = -8014615357825392276L;

	private List<HttpRequestInfo> reqRecords = new LinkedList<HttpRequestInfo>();

	private String requestPath = null;

	private String authorization = null;

	private String responseText = null;

	private byte[] responseBytes = null;

	private String requestMethod = null;

	private byte[] requestBody = null;

	private Integer responseStatusCode;

	public HttpRequestCollectorServlet(String responseText) {
		this(null, responseText);
	}

	public HttpRequestCollectorServlet(Integer responseStatusCode, String responseText) {
		this.responseStatusCode = responseStatusCode;
		this.responseText = responseText;
	}

	public HttpRequestCollectorServlet(byte[] responseBytes) {
		this(null, responseBytes);
	}

	public HttpRequestCollectorServlet(Integer responseStatusCode, byte[] responseBytes) {
		this.responseStatusCode = responseStatusCode;
		this.responseBytes = responseBytes;
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		reqRecords.add(new HttpRequestInfo(HttpMethod.GET, req.getParameterMap()));
		requestPath = req.getRequestURI();
		authorization = req.getHeader("Authorization");
		requestMethod = req.getMethod();
		
		if (responseStatusCode != null) {
			resp.setStatus(responseStatusCode);
		}

		if (responseText != null) {
			resp.getWriter().print(responseText);
			resp.getWriter().flush();
		} else if (responseBytes != null) {
			resp.getOutputStream().write(responseBytes, 0, responseBytes.length);
			resp.getOutputStream().flush();
		}
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		reqRecords.add(new HttpRequestInfo(HttpMethod.POST, req.getParameterMap()));
		requestPath = req.getRequestURI();
		authorization = req.getHeader("Authorization");
		requestMethod = req.getMethod();
		requestBody = readRequestBody(req);

		if (responseStatusCode != null) {
			resp.setStatus(responseStatusCode);
		}

		if (responseText != null) {
			resp.getWriter().print(responseText);
			resp.getWriter().flush();
		} else if (responseBytes != null) {
			resp.getOutputStream().write(responseBytes, 0, responseBytes.length);
			resp.getOutputStream().flush();
		}
	}

	@Override
	protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		reqRecords.add(new HttpRequestInfo(HttpMethod.PUT, req.getParameterMap()));
		requestPath = req.getRequestURI();
		authorization = req.getHeader("Authorization");
		requestMethod = req.getMethod();
		requestBody = readRequestBody(req);

		if (responseStatusCode != null) {
			resp.setStatus(responseStatusCode);
		}

		if (responseText != null) {
			resp.getWriter().print(responseText);
			resp.getWriter().flush();
		} else if (responseBytes != null) {
			resp.getOutputStream().write(responseBytes, 0, responseBytes.length);
			resp.getOutputStream().flush();
		}
	}

	@Override
	protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		reqRecords.add(new HttpRequestInfo(HttpMethod.DELETE, req.getParameterMap()));
		requestPath = req.getRequestURI();
		authorization = req.getHeader("Authorization");
		requestMethod = req.getMethod();

		if (responseStatusCode != null) {
			resp.setStatus(responseStatusCode);
		}

		if (responseText != null) {
			resp.getWriter().print(responseText);
			resp.getWriter().flush();
		} else if (responseBytes != null) {
			resp.getOutputStream().write(responseBytes, 0, responseBytes.length);
			resp.getOutputStream().flush();
		}
	}

	private byte[] readRequestBody(HttpServletRequest request) throws UnsupportedEncodingException, IOException {
		byte[] bodyBytes = BinaryUtils.readBytes(request.getInputStream());
		return bodyBytes;

		// return ByteArray.wrap(bodyBytes);

		// BufferedReader reader = new BufferedReader(new
		// InputStreamReader(request.getInputStream(), "UTF-8"));
		// String line = null;
		// StringBuilder builder = new StringBuilder();
		// while((line = reader.readLine()) != null){
		// builder.append(line);
		// }
		// return builder.toString();
	}

	public Iterator<HttpRequestInfo> getRequestRecords() {
		return reqRecords.iterator();
	}

	public String getRequestPath() {
		return requestPath;
	}

	public String getAuthorization() {
		return authorization;
	}

	public String getRequestMethod() {
		return requestMethod;
	}

	public byte[] getRequestBody() {
		return requestBody;
	}

	public void clearRequestRecords() {
		reqRecords.clear();
		requestPath = null;
	}
}
